#ifndef _MPI_VENC_H_
#define _MPI_VENC_H_


#ifdef __cplusplus
extern "C" {
#endif

#define    NUM_FRAME_TYPES         3     // I/P/B frames
#define    MAX_PREVIEW_NUM         1
#define    MULTI_STREAM_MAX_NUM    4

// Intra bias limit
#define   INTRABIAS_MIN            1
#define   INTRABIAS_MAX            4000

#define   ARRAY_SIZE(array)        (sizeof(array) / sizeof(array[0]))
#define   MByte(x)                ((x) << 20)

    typedef enum __sgks_mpi_venc_stream_state
    {
        VENC_STREAM_STATE_UNKNOWN              = 0,    // uninitialized or unconfigured
        VENC_STREAM_STATE_READY_FOR_ENCODING   = 1,    // configured ready, but not started encoding yet
        VENC_STREAM_STATE_ENCODING             = 2,    // encoding
        VENC_STREAM_STATE_STARTING             = 3,    // transition state: starting to encode
        VENC_STREAM_STATE_STOPPING             = 4,    // transition state: stopping encoding
        VENC_STREAM_STATE_ERROR                = 255,  // known error
    }sgks_mpi_venc_stream_state_e;

    typedef enum __sgks_mpi_venc_source_buffer_state
    {
        VENC_SOURCE_BUFFER_STATE_UNKNOWN   = 0,    // uninitialized or unconfigured
        VENC_SOURCE_BUFFER_STATE_IDLE      = 1,    // configured, but not used by any stream to encode
        VENC_SOURCE_BUFFER_STATE_BUSY      = 2,    // configured and used by at least one stream to encode
        VENC_SOURCE_BUFFER_STATE_ERROR     = 255,  // known error
    } sgks_mpi_venc_source_buffer_state_e;

    typedef enum __sgks_mpi_venc_gop
    {
        MEDIA_GOP_SIMPLE = 0,
        MEDIA_GOP_ADVANCED,
        MEDIA_GOP_P2B2REF,
        MEDIA_GOP_P2B3REF,
        MEDIA_GOP_P2B3_ADV,
        MEDIA_GOP_NONE,
        MEDIA_GOP_NON_REF_P,
        MEDIA_GOP_HI_P,
        MEDIA_GOP_NUM,
    } sgks_mpi_venc_gop_e;

    typedef enum __sgks_mpi_venc_brc
    {
        VENC_BRC_CBR = 1,
        VENC_BRC_PCBR,
        VENC_BRC_VBR,
        VENC_BRC_SCBR,
    } sgks_mpi_venc_brc_e;

    typedef struct __sgks_venc_h264_quality
    {
        u8 qp_min_I;
        u8 qp_min_P;
        u8 qp_min_B;
    } sgks_venc_h264_quality_s;

    typedef enum __sgks_mpi_stream_id
    {
        MEDIA_MAIN_STREAM           = (1 << 0),
        MEDIA_2ND_STREAM            = (1 << 1),
        MEDIA_3RD_STREAM            = (1 << 2),
        MEDIA_4TH_STREAM            = (1 << 3),
        MEDIA_STREAM_ID_TOTAL_NUM   = 4,
        MEDIA_ALL_STREAM            = ((1 << MEDIA_STREAM_ID_TOTAL_NUM) - 1),
    } sgks_mpi_stream_id_e;

    typedef enum __sgks_mpi_cavlc_params
    {
        MEDIA_MAX_CAVLC_BITRATE = MByte(2),
        MEDIA_MAX_CAVLC_STREAM_COUNT = 1,
        MEDIA_MAX_CAVLC_STREAM_WIDTH = MAX_WIDTH_IN_CAVLC,
        MEDIA_MAX_CAVLC_STREAM_HEIGHT = MAX_HEIGHT_IN_CAVLC,
    } sgks_mpi_cavlc_params_s;

    typedef enum __sgks_mpi_venc_realtime_update_param_bit_flags
    {
        VENC_REALTIME_PARAM_CBR_MODIFY_BIT             = (1 << 0),
        VENC_REALTIME_PARAM_CUSTOM_FRAME_RATE_BIT      = (1 << 1),
        VENC_REALTIME_PARAM_QP_LIMIT_BIT               = (1 << 2),
        VENC_REALTIME_PARAM_GOP_BIT                    = (1 << 3),
        VENC_REALTIME_PARAM_CUSTOM_VI_FPS_BIT          = (1 << 4),
        VENC_REALTIME_PARAM_INTRA_MB_ROWS_BIT          = (1 << 5),
        VENC_REALTIME_PARAM_PREVIEW_A_FRAME_RATE_BIT   = (1 << 6),
        VENC_REALTIME_PARAM_QP_ROI_MATRIX_BIT          = (1 << 7),
        VENC_REALTIME_PARAM_PANIC_MODE_BIT             = (1 << 8),
        VENC_REALTIME_PARAM_QUANT_MATRIX_BIT           = (1 << 9),
        VENC_REALTIME_PARAM_MONOCHROME_BIT             = (1 << 10),
        VENC_REALTIME_PARAM_INTRA_BIAS_BIT             = (1 << 11),
        VENC_REALTIME_PARAM_SCENE_DETECT_BIT           = (1 << 12),
        VENC_REALTIME_PARAM_BIAS_VALUE_BIT             = (1 << 13),
    } sgks_mpi_venc_realtime_update_param_bit_flags_e;

    typedef enum __sgks_mpi_venc_frame_rate_bit_shift
    {
        VENC_DENOMINATOR_BIT_SHIFT = 30,
        VENC_SCAN_FORMAT_BIT_SHIFT = 31,
    } sgks_mpi_venc_frame_rate_bit_shift_e;

    typedef enum __sgsk_mpi_venc_brc_mode
    {
        VENC_CBR_MODE = 0,
        VENC_VBR_MODE,
        VENC_CBR_QUALITY_MODE,
        VENC_VBR_QUALITY_MODE,
        VENC_CBR2_MODE,
        VENC_VBR2_MODE,
        VENC_BRC_MODE_NUM,
    } sgks_mpi_venc_brc_mode_e;

    typedef enum __sgks_mpi_venc_state
    {
        STATE_IDLE                = 0,
        STATE_PREVIEW             = 1,
        STATE_ENCODING            = 2,
        STATE_STILL_CAPTURE       = 3,
        STATE_DECODING            = 4,
        STATE_TRANSCODING         = 5,
        STATE_DUPLEX              = 6,
        STATE_ENCODE_STARTING     = 7,
        STATE_ENCODE_STOPPING     = 8,
        STATE_PREVIEW_STARTING    = 9,
        STATE_INIT                = 0xFF,
    } sgks_mpi_venc_state_e;

    typedef enum __sgks_venc_channel
    {
        VENC_CHANNEL_1 = 0,
        VENC_CHANNEL_2,
        VENC_CHANNEL_3,
        VENC_CHANNEL_4,
        VENC_CHANNEL_NUM,
    } sgks_venc_channel_e;

    typedef enum __sgks_venc_aspect_ratio_type
    {
        VENC_ASPECT_RATIO_UNSPECIFIED           = 0,
        VENC_ASPECT_RATIO_1_1_SQUARE_PIXEL      = 1,
        VENC_ASPECT_RATIO_PAL_4_3               = 2,
        VENC_ASPECT_RATIO_NTSC_4_3              = 3,
        VENC_ASPECT_RATIO_CUSTOM                = 255,
    } sgks_venc_aspect_ratio_type_e;

    typedef struct __sgks_venc_pic_info_s
    {
        u16 ar_x;
        u16 ar_y;
        u8  frame_mode;
        u8  reserved[3];
        u32 rate;
        u32 scale;
        u16 width;
        u16 height;
        u32 reserved2[4];    // for future use
    } sgks_venc_pic_info_s;

    typedef struct __sgks_venc_change_qp_limit
    {
        u32   id;
        u8  qp_min_on_I;
        u8  qp_max_on_I;
        u8  qp_min_on_P;
        u8  qp_max_on_P;
        u8  qp_min_on_B;
        u8  qp_max_on_B;
        u8  i_qp_reduce;
        u8  p_qp_reduce;
        u8  adapt_qp;
        u8  skip_flag;
        u8  reserved[2];
    } sgks_venc_change_qp_limit_s;

    typedef struct __sgks_mpi_venc_format
    {
        u32 id;
        u8  encode_type;      // 0: none 1: H.264 // 2: MJPEG
        u8  source;           // 0: main source buffer (MEDIA_ENCODE_SOURCE_MAIN_BUFFER)
        // 1: secondary source buffer(MEDIA_ENCODE_SOURCE_SECOND_BUFFER)
        u8  reserved[1];
        u8  enable_individual_y_uv_offset;
        u16 encode_width;       // encode width
        u16 encode_height;      // encode height
        u16 encode_x;           // crop start x
        u16 encode_y;           // crop start y
        u16 encode_uv_x;        // crop start uv x
        u16 encode_uv_y;        // crop start uv y
    } sgks_mpi_venc_format_s;

    typedef struct __sgks_venc_h264_config
    {
        u32   id;
        u32 average_bitrate;
        sgks_venc_pic_info_s    pic_info;    // output

        u16 M;
        u16 N;
        u8  idr_interval;
        u8  gop_model;
        u8  bitrate_control;

        u8  slice_alpha_c0_offset_div2; // alpha value for deblocking filter, -6 to 6 inclusive, from weak to strong filtering
        u8  slice_beta_offset_div2;     // beta value for deblocking filter, -6 to 6 inclusive, from weak to strong filtering
        u8  deblocking_filter_enable;   // deblocking filter enable 1: enable to use manual control
        // 0:disable  2:(default) auto use internal calculated alpha and beta
        u8  entropy_codec;              // 0: (default)CABAC-Main Profile, 1: CAVLC- Baseline Profile

        u8  force_intlc_tb_iframe;      // 0: (default), first top field to be I-frame in interlaced encoding,
        // 1: force first two fields to be I-frame in interlaced encoding
        u8  allow_i_adv;                // TOREVIEW: all below items are added to enable advanced control on encoding parameters
        u8  cpb_buf_idc;

        u8  en_panic_rc         :  2;
        u8  cpb_cmp_idc         :  2;
        u8  fast_rc_idc         :  4;
        u8  hflip               :  1;
        u8  vflip               :  1;
        u8  rotate_clockwise    :  1;
#define VENC_H264_CHROMA_FORMAT_YUV420     0
#define VENC_H264_CHROMA_FORMAT_MONO       1
        u8  chroma_format       :  1;
        u8  high_profile        :  1;
        u8  reserved2           :  3;

        // rate control related
        u8  qp_min_on_I;
        u8  qp_max_on_I;
        u8  qp_min_on_P;
        u8  qp_max_on_P;
        u8  qp_min_on_B;
        u8  qp_max_on_B;
        u8  i_qp_reduce;
        u8  p_qp_reduce;
        u8  adapt_qp;
        u8  skip_flag;
        u8  intra_refresh_mb_rows;     // intra refresh MB rows
        u8  au_type;                   // h264 syntax config  0:No AUD, No SEI; 1:AUD before SPS, PPS, with SEI;
        // 2:AUD after SPS, PPS, with SEI; 3:No AUD, with SEI
        u32 cpb_user_size;
        s8  qp_delta[NUM_FRAME_TYPES][4];
        u8  qp_roi_enable;
        u8  panic_div;
        u8  reserved[2];
        u32 pic_size_control;

        // extend rate control related
        u16 intrabias_P;
        u16 intrabias_B;

        //addtitional idr when scene change detect
        u8  enable_scene_detect;

        //tune the AQP and mode bias
        s8  intra16x16_bias;    // -64~64, clamp the negative value to -64 to avoid underflow
        s8  intra4x4_bias;      // -64~64, clamp the negative value to -64 to avoid underflow
        s8  inter16x16_bias;    // -64~64, clamp the negative value to -64 to avoid underflow
        s8  inter8x8_bias;      // -64~64, clamp the negative value to -64 to avoid underflow

        s8  direct16x16_bias;   // -64~64, clamp the negative value to -64 to avoid underflow
        s8  direct8x8_bias;     // -64~64, clamp the negative value to -64 to avoid underflow
        s8  me_lambda_qp_offset;
    } sgks_venc_h264_config_s;

    typedef struct __sgks_venc_mjpeg_config
    {
        u32   id;
#define VENC_JPEG_CHROMA_FORMAT_YUV422     0
#define VENC_JPEG_CHROMA_FORMAT_YUV420     1
#define VENC_JPEG_CHROMA_FORMAT_MONO       2
        u8  chroma_format;
        u8  quality;                    // 1 ~ 100 ,  100 is best quality
        u8  hflip               :  1;
        u8  vflip               :  1;
        u8  rotate_clockwise    :  1;
        u8  reserved1           :  5;
        u8  reserved2;
        u8  *jpeg_quant_matrix;
    } sgks_venc_mjpeg_config_s;

    typedef struct __sgks_stream_encode_config
    {
        sgks_venc_h264_config_s  h264_encode_config;
        sgks_venc_mjpeg_config_s  jpeg_encode_config;
        u8 frame_rate_division_factor;
        u8 frame_rate_multiplication_factor;
        u8 reserved[2];
    } sgks_stream_encode_config_s;

    typedef struct __sgks_mpi_venc_bitrate_param
    {
        u32      streamId;      /*stream index for setting the bitrate.*/
        sgks_mpi_venc_brc_mode_e        brcMode;
        u32      cbrAvgBps;
        u32      vbrMinbps;   /*vbr mode, min bit rate.*/
        u32      vbrMaxbps;  /*vbr mode, max bit rate.*/
    } sgks_mpi_venc_bitrate_param_s;

    typedef struct __sgks_mpi_venc_stream_params
    {
        u32                            maxWidth;    /*encode video max width.*/
        u32                            maxHeight;   /*encode video max height.*/
        u32                            framerate;   /*encode stream framerate.*/
        u8                             keepAspRat;  /*encode video keep aspect ratio.*/
        sgks_mpi_venc_stream_state_e   state;
        sgks_mpi_venc_format_s         format;      /*one encode stream  format.*/
        sgks_mpi_venc_bitrate_param_s  bitrate;
        sgks_stream_encode_config_s    *config;
    } sgks_mpi_venc_stream_params_s;

    typedef struct __sgks_mpi_venc_handle
    {
        u32  hMDI;  /*MDI driver handle*/
        u32  activeEncodingNum; /*active encoding stream number.*/
        sgks_mpi_venc_stream_params_s encodeStreams[VENC_STREAM_NUM]; /*encode streams parameters.*/
    } sgks_mpi_venc_handle_s;

    typedef struct sgks_mpi_venc_change_framerate_factor
    {
        u32 id;
        u8  ratio_numerator;
        u8  ratio_denominator;
        u16 reserved;
    } sgks_mpi_venc_change_framerate_factor_s;

    typedef struct sgks_source_buffer_format_all
    {
        u16 main_width;                     // width of main source buffer
        u16 main_height;                    // height of main source buffer
        u16 main_deintlc_for_intlc_vi;      // deintlc mode of main source buffer
        u16 second_width;                   // width of secondary source buffer
        u16 second_height;                  // height of secondary source buffer
        u16 second_input_width;             // width of second input window
        u16 second_input_height;            // height of second input window
        u16 second_deintlc_for_intlc_vi;    // deintlc mode of second source buffer
        u16 third_width;                    // width of third source buffer
        u16 third_height;                   // height of third source buffer
        u16 third_input_width;              // width of main input window
        u16 third_input_height;             // width of main input window
        u16 third_deintlc_for_intlc_vi;     // deintlc mode of third source buffer
        u16 fourth_width;                   // width of fourth source buffer
        u16 fourth_height;                  // height of fourth source buffer
        u16 fourth_input_width;             // width of fourth source buffer
        u16 fourth_input_height;            // height of fourth source buffer
        u16 fourth_deintlc_for_intlc_vi;    // deintlc mode of fourth source buffer

        u8  intlc_scan;                     //0: OFF  1: use progressive VI to encode interlaced video
        u8  second_unwarp;
        u8  third_unwarp;
        u8  fourth_unwarp;
    } sgks_source_buffer_format_all_s;

    typedef struct sgks_preview_buffer_format_all
    {
        u16 main_preview_width;         // width of main preview buffer (preview B)
        u16 main_preview_height;        // height of main preview buffer (preview B)
        u16 second_preview_width;       // width of second preview buffer (preview A)
        u16 second_preview_height;      // height of second preview buffer (preview A)
    } sgks_preview_buffer_format_all_s;

    typedef struct __sgks_source_buffer_type_all
    {
        sgks_source_buffer_type_ex_t   main_buffer_type;
        sgks_source_buffer_type_ex_t   second_buffer_type;
        sgks_source_buffer_type_ex_t   third_buffer_type;
        sgks_source_buffer_type_ex_t   fourth_buffer_type;
    } sgks_source_buffer_type_all_s;

    typedef struct __sgks_venc_digital_zoom
    {
        u32 zoom_factor_x;      // 16.16 format
        u32 zoom_factor_y;      // 16.16 format
        u32 center_offset_x;    // 16.16 format
        u32 center_offset_y;    // 16.16 format
    } sgks_venc_digital_zoom_s;

    typedef struct __sgks_venc_dptz_param
    {
        u32  channelId; /*channel index.*/
        u32  zoomFactor; /*zoom factor.*/
        s32  offsetX; /*zoom offset x.*/
        s32  offsetY; /*zoom offset y.*/
    } sgks_venc_dptz_param_s;

    typedef struct __sgks_venc_digital_zoom2
    {
        u32 source;
        u32 input_width;
        u32 input_height;
        u32 input_offset_x;
        u32 input_offset_y;
    } sgks_venc_digital_zoom2_s;

    typedef struct sgks_venc_encode_limit
    {
        u32        width_max;
        u32        height_max;
        u32        width_min;
        u32        height_min;
        u32        h264_rotate_width_min;
        u32        h264_rotate_height_min;
    } sgks_venc_encode_limit_s;

    typedef struct
    {
        u32 wr_ptr;
        u32 rd_ptr;
        u16 encode_from_arm_always;
        u16 prevc_from_arm_always;
        u32 reserved;
    } ARM2DSP_HeadInfo_t;

    typedef struct
    {
        u32 y_addr;
        u32 uv_addr;
        u32 repeat_nums;
        u16 pitch;
        u16 height;
    } ARM2DSP_FrameInfo_t;

    typedef struct
    {
        ARM2DSP_HeadInfo_t headinfo;
        ARM2DSP_FrameInfo_t frameinfo[15];
    } ARM2DSP_EncInfo_t;

    typedef struct
    {
        u32 enc_enable;
        u32 y_addr;
        u32 uv_addr;
        u32 repeat_nums;
        u16 pitch;
        u16 height;
        u8 area_id;
        u8 zoom_enable;
    } sgks_YuvEncInfo_t;

    typedef struct __sgks_venc_jpeg_info
    {
        u32 addr;
        u32 size;
    }sgks_venc_jpeg_info_s;

    int sgks_mpi_venc_init(void);
    int sgks_mpi_venc_get_params(sgks_mpi_venc_param_type_e paramType, void *pParam);
    int sgks_mpi_venc_set_params(sgks_mpi_venc_param_type_e paramType, void *pParam);
    int sgks_mpi_venc_set_config(sgks_mpi_venc_config_type_e configType, void *pConfig);
    int sgks_mpi_venc_get_config(sgks_mpi_venc_config_type_e configType, void *pConfig);
    int sgks_mpi_venc_state_control(sgks_mpi_venc_state_control_type_e stateControlType, u32 streamId);
    int sgks_mpi_venc_get_stream(u32 streamId, sgks_mpi_venc_stream_s *pStream);
    int sgks_mpi_venc_deinit(void);
    int sgks_mpi_venc_get_state(u32 *state, u32 streamId);
    
    int sgks_mpi_venc_map_encode_buf(sgks_mpi_venc_enc_buf_s *info);
    int sgks_mpi_venc_unmap_encode_buf(void);
    int sgks_mpi_venc_feed_yuv_to_encode(sgks_mpi_venc_yuv_enc_s *info);
    int sgks_mpi_venc_yuv_to_jpeg( u32 srcYuv420Addr, u16 srcWidth, u16 srcHeight, u32 *dstJpegAddr, u32 *dstSize);

    int venc_check_encode_format_limit(u32 stream_id);
    int venc_cmd_encode_size_setup(int stream);
#ifdef __cplusplus
}
#endif

#endif
